/*
    This file is part of Akonadi Contact.

    Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "emaileditwidget.h"

#include "autoqpointer_p.h"

#include <QtCore/QEvent>
#include <QtCore/QString>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QToolButton>

#include <kabc/addressee.h>
#include <kacceleratormanager.h>
#include <kinputdialog.h>
#include <klineedit.h>
#include <KListWidget>
#include <klocalizedstring.h>
#include <kmessagebox.h>
#include <kpimutils/email.h>

class EmailAddressExtracter : public QObject
{
  public:
    EmailAddressExtracter( KLineEdit *lineEdit )
      : QObject( lineEdit ), mLineEdit( lineEdit )
    {
      lineEdit->installEventFilter( this );
    }

    virtual bool eventFilter( QObject *watched, QEvent *event )
    {
      if ( watched == mLineEdit && event->type() == QEvent::FocusOut ) {
        const QString fullEmailAddress = mLineEdit->text();
        const QString extractedEmailAddress = KPIMUtils::extractEmailAddress( fullEmailAddress );
        mLineEdit->setText( extractedEmailAddress );
      }

      return QObject::eventFilter( watched, event );
    }

  private:
    KLineEdit *mLineEdit;
};

class EmailItem : public QListWidgetItem
{
  public:
    EmailItem( const QString &text, QListWidget *parent, bool preferred )
      : QListWidgetItem( text, parent ), mPreferred( preferred )
    {
      format();
    }

    void setPreferred( bool preferred ) { mPreferred = preferred; format(); }
    bool preferred() const { return mPreferred; }

  private:
    void format()
    {
      QFont f = font();
      f.setBold( mPreferred );
      setFont( f );
    }

  private:
    bool mPreferred;
};

EmailEditWidget::EmailEditWidget( QWidget *parent )
  : QWidget( parent )
{
  QHBoxLayout *layout = new QHBoxLayout( this );
  layout->setMargin( 0 );
  layout->setSpacing( KDialog::spacingHint() );

  mEmailEdit = new KLineEdit;
  new EmailAddressExtracter( mEmailEdit );
  connect( mEmailEdit, SIGNAL(textChanged(QString)),
           SLOT(textChanged(QString)) );
  layout->addWidget( mEmailEdit );

  mEditButton = new QToolButton;
  mEditButton->setText( QLatin1String( "..." ) );
  connect( mEditButton, SIGNAL(clicked()), SLOT(edit()) );
  layout->addWidget( mEditButton );
}

EmailEditWidget::~EmailEditWidget()
{
}

void EmailEditWidget::setReadOnly( bool readOnly )
{
  mEmailEdit->setReadOnly( readOnly );
  mEditButton->setEnabled( !readOnly );
}

void EmailEditWidget::loadContact( const KABC::Addressee &contact )
{
  mEmailList = contact.emails();

  if ( !mEmailList.isEmpty() ) {
    mEmailEdit->setText( mEmailList.first() );
  } else {
    mEmailEdit->setText( QString() );
  }
}

void EmailEditWidget::storeContact( KABC::Addressee &contact ) const
{
  QStringList emails( mEmailList );

  // the preferred address is always the first one, remove it...
  if ( !emails.isEmpty() ) {
    emails.removeFirst();
  }

  // ... and prepend the one from the line edit
  if ( !mEmailEdit->text().isEmpty() ) {
      emails.prepend( mEmailEdit->text().toLower() );
  }

  contact.setEmails( emails );
}

void EmailEditWidget::edit()
{
  AutoQPointer<EmailEditDialog> dlg = new EmailEditDialog( mEmailList, this );

  if ( dlg->exec() ) {
    if ( dlg->changed() ) {
      mEmailList = dlg->emails();
      if ( !mEmailList.isEmpty() ) {
        mEmailEdit->setText( mEmailList.first() );
      } else {
        mEmailEdit->setText( QString() );
      }
    }
  }
}

void EmailEditWidget::textChanged( const QString &text )
{
  if ( !mEmailList.isEmpty() ) {
    mEmailList.removeFirst();
  }

  mEmailList.prepend( text );
}


EmailEditDialog::EmailEditDialog( const QStringList &list, QWidget *parent )
  : KDialog( parent )
{
  setCaption( i18n( "Edit Email Addresses" ) );
  setButtons( KDialog::Ok | KDialog::Cancel );
  setDefaultButton( KDialog::Cancel );

  QWidget *page = new QWidget( this );
  setMainWidget( page );

  QGridLayout *topLayout = new QGridLayout( page );
  topLayout->setSpacing( spacingHint() );
  topLayout->setMargin( 0 );

  mEmailListBox = new KListWidget( page );
  mEmailListBox->setSelectionMode( QAbstractItemView::SingleSelection );

  // Make sure there is room for the scrollbar
  mEmailListBox->setMinimumHeight( mEmailListBox->sizeHint().height() + 30 );
  connect( mEmailListBox, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
           SLOT(selectionChanged()) );
  connect( mEmailListBox, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
           SLOT(edit()) );
  topLayout->addWidget( mEmailListBox, 0, 0, 5, 2 );

  mAddButton = new QPushButton( i18n( "Add..." ), page );
  connect( mAddButton, SIGNAL(clicked()), SLOT(add()) );
  topLayout->addWidget( mAddButton, 0, 2 );

  mEditButton = new QPushButton( i18n( "Edit..." ), page );
  mEditButton->setEnabled( false );
  connect( mEditButton, SIGNAL(clicked()), SLOT(edit()) );
  topLayout->addWidget( mEditButton, 1, 2 );

  mRemoveButton = new QPushButton( i18n( "Remove" ), page );
  mRemoveButton->setEnabled( false );
  connect( mRemoveButton, SIGNAL(clicked()), SLOT(remove()) );
  topLayout->addWidget( mRemoveButton, 2, 2 );

  mStandardButton = new QPushButton( i18n( "Set as Standard" ), page );
  mStandardButton->setEnabled( false );
  connect( mStandardButton, SIGNAL(clicked()), SLOT(standard()) );
  topLayout->addWidget( mStandardButton, 3, 2 );

  topLayout->setRowStretch( 4, 1 );

  QStringList items = list;
  if ( items.removeAll( QLatin1String( "" ) ) > 0 ) {
    mChanged = true;
  } else {
    mChanged = false;
  }

  QStringList::ConstIterator it;
  bool preferred = true;
  for ( it = items.constBegin(); it != items.constEnd(); ++it ) {
    new EmailItem( *it, mEmailListBox, preferred );
    preferred = false;
  }

  // set default state
  KAcceleratorManager::manage( this );

  setInitialSize( QSize( 400, 200 ) );
}

EmailEditDialog::~EmailEditDialog()
{
}

QStringList EmailEditDialog::emails() const
{
  QStringList emails;

  for ( int i = 0; i < mEmailListBox->count(); ++i ) {
    EmailItem *item = static_cast<EmailItem*>( mEmailListBox->item( i ) );
    if ( item->preferred() ) {
      emails.prepend( item->text() );
    } else {
      emails.append( item->text() );
    }
  }

  return emails;
}

void EmailEditDialog::add()
{
  bool ok = false;

  QString email = KInputDialog::getText( i18n( "Add Email" ), i18n( "New Email:" ),
                                         QString(), &ok, this );

  if ( !ok ) {
    return;
  }

  email = KPIMUtils::extractEmailAddress( email.toLower() );

  // check if item already available, ignore if so...
  for ( int i = 0; i < mEmailListBox->count(); ++i ) {
    if ( mEmailListBox->item( i )->text() == email ) {
      return;
    }
  }

  new EmailItem( email, mEmailListBox, ( mEmailListBox->count() == 0 ) );

  mChanged = true;
}

void EmailEditDialog::edit()
{
  bool ok = false;

  QListWidgetItem *item = mEmailListBox->currentItem();

  QString email = KInputDialog::getText( i18n( "Edit Email" ),
                                         i18nc( "@label:textbox Inputfield for an email address", "Email:" ),
                                         item->text(), &ok, this );

  if ( !ok ) {
    return;
  }

  email = KPIMUtils::extractEmailAddress( email.toLower() );

  // check if item already available, ignore if so...
  for ( int i = 0; i < mEmailListBox->count(); ++i ) {
    if ( mEmailListBox->item( i )->text() == email ) {
      return;
    }
  }

  EmailItem *eitem = static_cast<EmailItem*>( item );
  eitem->setText( email );

  mChanged = true;
}

void EmailEditDialog::remove()
{
  const QString address = mEmailListBox->currentItem()->text();

  const QString text = i18n( "<qt>Are you sure that you want to remove the email address <b>%1</b>?</qt>", address );
  const QString caption = i18n( "Confirm Remove" );

  if ( KMessageBox::warningContinueCancel( this, text, caption, KGuiItem( i18n( "&Delete" ), QLatin1String( "edit-delete" ) ) ) == KMessageBox::Continue ) {
    EmailItem *item = static_cast<EmailItem*>( mEmailListBox->currentItem() );

    const bool preferred = item->preferred();
    mEmailListBox->takeItem( mEmailListBox->currentRow() );
    if ( preferred ) {
      item = dynamic_cast<EmailItem*>( mEmailListBox->item( 0 ) );
      if ( item ) {
        item->setPreferred( true );
      }
    }

    mChanged = true;
  }
}

bool EmailEditDialog::changed() const
{
  return mChanged;
}

void EmailEditDialog::standard()
{
  for ( int i = 0; i < mEmailListBox->count(); ++i ) {
    EmailItem *item = static_cast<EmailItem*>( mEmailListBox->item( i ) );
    if ( i == mEmailListBox->currentRow() ) {
      item->setPreferred( true );
    } else {
      item->setPreferred( false );
    }
  }

  mChanged = true;
}

void EmailEditDialog::selectionChanged()
{
  int index = mEmailListBox->currentRow();
  bool value = ( index >= 0 ); // An item is selected

  mRemoveButton->setEnabled( value );
  mEditButton->setEnabled( value );
  mStandardButton->setEnabled( value );
}

